package cn.lanqiao.springbootproject.controller;

import cn.lanqiao.springbootproject.service.UserService;
import cn.lanqiao.springbootproject.util.CurrentUserUtil;
import cn.lanqiao.springbootproject.util.Result;
import cn.lanqiao.springbootproject.vo.QueryUserVO;
import cn.lanqiao.springbootproject.vo.UserRoleVO;
import cn.lanqiao.springbootproject.vo.UserVO;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.digest.DigestUtils;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Log4j2
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    UserService userService;

    @Autowired
    RedisTemplate redisTemplate;

    @Value("${jwt.token.key}")
    String key;

    @Cacheable(value = "userList", key = "#pageNum")
    @PostMapping("/query")
    public Result query(@RequestBody QueryUserVO queryUserVO) {
        PageHelper.startPage(queryUserVO.getPageNum(), queryUserVO.getPageSize());
        List<UserVO> userList = userService.queryUserList();
        PageInfo<UserVO> pageInfo = new PageInfo<>(userList);
        return Result.success(pageInfo);
    }

    @PostMapping("/login")
    public Result login(@RequestBody QueryUserVO queryUserVO, HttpSession session) {

        //验证码认证
        if (((Integer) redisTemplate.opsForValue().get(session.getId())) != queryUserVO.getCode()) {
            return Result.fail(600, "验证码错误！！");
        }

        UserRoleVO userRoleVO = userService.userLogin(queryUserVO);
        if (userRoleVO == null) {
            return Result.fail(601, "该用户名不存在！");
        }
        if (BCrypt.checkpw(queryUserVO.getPassword(), userRoleVO.getPassword())) {
            //签发token
            String token = JWT.create()
                    .withClaim("userId", userRoleVO.getUserId())//jwt中存用户id
                    .withClaim("userName", userRoleVO.getUserName())//jwt中存用户名
                    .withClaim("roleId", userRoleVO.getRoleId())//角色id
                    .withClaim("roleName", userRoleVO.getRoleName())//角色名
                    .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60))//设置失效时间一小时
                    .sign(Algorithm.HMAC256(key));//设置秘钥。
            return Result.success(token);
        } else {
            return Result.fail(602, "用户密码错误！");
        }
    }

    @PostMapping("/login1")
    public Result login1(QueryUserVO queryUserVO) {
        queryUserVO.setPassword(DigestUtils.md5Hex(queryUserVO.getPassword() + "!@#123RTY"));
        UserRoleVO userRoleVO = userService.userLogin(queryUserVO);
        if (userRoleVO != null) {
            //签发token
            String token = JWT.create()
                    .withClaim("userId", userRoleVO.getUserId())//jwt中存用户id
                    .withClaim("userName", userRoleVO.getUserName())//jwt中存用户名
                    .withClaim("roleId", userRoleVO.getRoleId())//角色id
                    .withClaim("roleName", userRoleVO.getRoleName())//角色名
                    .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60))//设置失效时间一小时
                    .sign(Algorithm.HMAC256("david"));//设置秘钥。
            return Result.success(token);
        } else {
            return Result.fail(600, "用户名或密码错误！");
        }
    }


    /**
     * 手机验证 + 有状态JWT
     *
     * @param queryUserVO
     * @return
     */
    @PostMapping("/login2")
    public Result login2(@RequestBody QueryUserVO queryUserVO) {

        //验证码认证
        if (((Integer) redisTemplate.opsForValue().get("phone-code:" + queryUserVO.getUserName())) != queryUserVO.getCode()) {
            return Result.fail(600, "验证码错误！！");
        }

        UserRoleVO userRoleVO = userService.userLogin(queryUserVO);
        if (userRoleVO == null) {
            return Result.fail(601, "该用户名不存在！");
        }

        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set("userToken:" + token, userRoleVO, 30, TimeUnit.MINUTES);
        return Result.success(token);

    }

    @PostMapping("/insert")
    public Result insert(@Valid @RequestBody UserRoleVO userRoleVO) {
        userRoleVO.setPassword(BCrypt.hashpw(userRoleVO.getPassword(), BCrypt.gensalt()));
        userService.insert(userRoleVO);
        return Result.success();
    }

    @GetMapping("/getUserByToken")
    public Result getUserByToken() {
        return Result.success(CurrentUserUtil.get());
    }

    @GetMapping("/getCode")
    public Result getVerificationCode(HttpSession session) {
        int code = 1000 + new Random().nextInt(9000);
        log.info("sessionId:{}", session.getId());
//        session.setAttribute("code",code);
        redisTemplate.opsForValue().set(session.getId(), code);

        return Result.success(code);
    }

    @GetMapping("/getPhoneCode/{phone}")
    public Result getPhoneCode(@PathVariable String phone) {
        int code = 1000 + new Random().nextInt(9000);
        //发送短信
        log.info("发送短信：{} , 验证码：{}", phone, code);
        //存储redis
        redisTemplate.opsForValue().set("phone-code:" + phone, code, 3, TimeUnit.MINUTES);
        return Result.success();
    }
}
